bitkeeper revision 1.376 (3f252286eVnrMT7PgP5t-QqVhRZAwQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 28 Jul 2003 13:17:58 +0000 (13:17 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 28 Jul 2003 13:17:58 +0000 (13:17 +0000)
traps.c, hypervisor-if.h:
  Allow virtualisation of interrupt gates as well as task gates. If the appropriate flag is sent to set_trap_table then that exception causes the master event enable bit to be cleared in teh shared_info structure.

xen/arch/i386/traps.c
xen/include/hypervisor-ifs/hypervisor-if.h
xenolinux-2.4.21-sparse/arch/xeno/kernel/traps.c

index 66e52c24568ee79b36c46657da8a489f24f675e5..119641767e3b961ed3d743b879277a8eb961b275 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/i386/traps.c
+ *  xen/arch/i386/traps.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
@@ -189,6 +189,7 @@ static void inline do_trap(int trapnr, char *str,
                           struct pt_regs * regs, 
                            long error_code, int use_error_code)
 {
+    struct task_struct *p = current;
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
     trap_info_t *ti;
     unsigned long fixup;
@@ -201,6 +202,8 @@ static void inline do_trap(int trapnr, char *str,
     gtb->error_code = error_code;
     gtb->cs         = ti->cs;
     gtb->eip        = ti->address;
+    if ( TI_GET_IF(ti) )
+        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
     return; 
 
  fault_in_hypervisor:
@@ -274,6 +277,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
     gtb->error_code = error_code;
     gtb->cs         = ti->cs;
     gtb->eip        = ti->address;
+    if ( TI_GET_IF(ti) )
+        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
     return; 
 
     /*
@@ -371,6 +376,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
 
 asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
 {
+    struct task_struct *p = current;
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
     trap_info_t *ti;
     unsigned long fixup;
@@ -403,13 +409,11 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
     {
         /* This fault must be due to <INT n> instruction. */
         ti = current->thread.traps + (error_code>>3);
-        if ( ti->dpl >= (regs->xcs & 3) )
+        if ( TI_GET_DPL(ti) >= (regs->xcs & 3) )
         {
             gtb->flags = GTBF_TRAP_NOCODE;
-            gtb->cs    = ti->cs;
-            gtb->eip   = ti->address;
             regs->eip += 2;
-            return;
+            goto finish_propagation;
         }
     }
     
@@ -417,8 +421,11 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
     ti = current->thread.traps + 13;
     gtb->flags      = GTBF_TRAP;
     gtb->error_code = error_code;
+ finish_propagation:
     gtb->cs         = ti->cs;
     gtb->eip        = ti->address;
+    if ( TI_GET_IF(ti) )
+        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
     return;
 
  gp_in_kernel:
@@ -718,16 +725,24 @@ long do_set_fast_trap(int idx)
      * The former range is used by Windows and MS-DOS.
      * Vector 0x80 is used by Linux and the BSD variants.
      */
-    if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) return -1;
+    if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) 
+        return -1;
 
     ti = current->thread.traps + idx;
 
+    /*
+     * We can't virtualise interrupt gates, as there's no way to get
+     * the CPU to automatically clear the events_mask variable.
+     */
+    if ( TI_GET_IF(ti) )
+        return -1;
+
     CLEAR_FAST_TRAP(&current->thread);
 
     current->thread.fast_trap_idx    = idx;
     current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
     current->thread.fast_trap_desc.b = 
-        (ti->address & 0xffff0000) | 0x8f00 | (ti->dpl&3)<<13;
+        (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
 
     SET_FAST_TRAP(&current->thread);
 
index ab5ca7943a3e9d8e1eed28761ba4683a4009b60e..adedd40607d4646a3db0bc7d04106ad378bd9494 100644 (file)
 /*
  * Send an array of these to HYPERVISOR_set_trap_table()
  */
+#define TI_GET_DPL(_ti)      ((_ti)->flags & 3)
+#define TI_GET_IF(_ti)       ((_ti)->flags & 4)
+#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
+#define TI_SET_IF(_ti,_if)   ((_ti)->flags |= (_if))
 typedef struct trap_info_st
 {
-    unsigned char  vector;  /* exception/interrupt vector */
-    unsigned char  dpl;            /* privilege level            */
-    unsigned short cs;     /* code selector              */
-    unsigned long  address; /* code address              */
+    unsigned char  vector;  /* exception vector                              */
+    unsigned char  flags;   /* 0-3: privilege level; 4: clear event enable?  */
+    unsigned short cs;     /* code selector                                 */
+    unsigned long  address; /* code address                                  */
 } trap_info_t;
 
 /*
index e9c2fd5a1cf9e8874ce734d932be8ce2e9affaab..85c6acb8f074552b3470b2bbe8a08ae251ddd7ae 100644 (file)
@@ -554,6 +554,7 @@ static void __init set_call_gate(void *a, void *addr)
 }
 
 
+/* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
 static trap_info_t trap_table[] = {
     {  0, 0, __KERNEL_CS, (unsigned long)divide_error                },
     {  1, 0, __KERNEL_CS, (unsigned long)debug                       },